﻿using System;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;
using ImageRecognition2.CustomControls;
using LowLevelGraphics.Filter;

using LowLevelGraphics.ColorSpaces;
using LowLevelGraphics.ImageFormats;

namespace LowLevelGraphics
{
    /// <summary>
    /// 
    /// </summary>
    public enum PIXEL_MODE
    {
        COLOR_ARGB_VALUE,
        COLOR_INTRGB_VALUE,
        GRAY_VALUE,
        COLOR_UINT
    }

    public delegate object SingleIntValuePixelDelegate(int _r);

    /// <summary>
    /// 
    /// </summary>
    [DebuggerDisplay("Width: {m_nWidth, Height: {m_nHeight}}")]
    unsafe public class UnsafeBitmap : IBitmap, ICloneable
    {
        protected static Dictionary<PixelFormat, int> m_aBytesPerPixelCount = new Dictionary<PixelFormat, int>(){
            {PixelFormat.Alpha,-1}, 
            //{PixelFormat.Canonical, -1},
            //{PixelFormat.DontCare, -1},
            //{PixelFormat.Extended, -1},
            {PixelFormat.Format16bppArgb1555, -1},
            {PixelFormat.Format16bppGrayScale, -1},
            {PixelFormat.Format16bppRgb555, -1},
            {PixelFormat.Format16bppRgb565, -1},
            {PixelFormat.Format1bppIndexed, -1},
            {PixelFormat.Format24bppRgb, 3},
            {PixelFormat.Format32bppArgb, 4},
            {PixelFormat.Format32bppPArgb, 4},
            {PixelFormat.Format32bppRgb, 3},
            {PixelFormat.Format48bppRgb, 3},
            {PixelFormat.Format4bppIndexed, -1},
            {PixelFormat.Format64bppArgb, -1},
            {PixelFormat.Format64bppPArgb, -1},
            {PixelFormat.Format8bppIndexed, -1},
            //{PixelFormat.Gdi, -1},
            //{PixelFormat.Indexed, -1},
            //{PixelFormat.Max, -1},
            //{PixelFormat.PAlpha, -1},
            //{PixelFormat.Undefined, -1}
        };
        public HashSet m_ForegroundEdgePixels = new HashSet();
        public HashSet m_BackgroundEdgePixels = new HashSet();
        protected HashSet<Color> m_aPalette = null;

        protected int m_nWidth = -1;
        protected int m_nHeight = -1;
        protected int m_nPixelCount = -1;

        /// <summary>
        /// normally we use Format32bppArgb here
        /// So we know now
        /// bytes are in this order in memory:
        /// b g r a, b g r a, ...
        /// </summary>
        protected PixelFormat m_PixelFormat = PixelFormat.Format32bppArgb;

        protected PixelData* m_PixelData = null;

        protected int m_PixelDataGetNextPixelIndex = 0;

        /// <summary>
        /// Pixel Data containing structural byte data of the bitmap
        /// </summary>
        public struct PixelDataCoordinates
        {
            public byte blue;
            public byte green;
            public byte red;
            public byte alpha;

            public int x;
            public int y;

            public PixelDataCoordinates(byte _alpha, byte _red, byte _green, byte _blue, int _x, int _y)
            {
                alpha = _alpha;
                blue = _blue;
                red = _red;
                green = _green;
                x = _x;
                y = _y;
            }

            public Point Point
            {
                get { return new Point(x, y); }
            }

            public Color Color
            {
                get { return Color.FromArgb(alpha, red, green, blue); }
            }
        }


        /// <summary>
        /// Pixel Data containing structural byte data of the bitmap
        /// </summary>
        protected struct PixelData
        {
            public byte blue;
            public byte green;
            public byte red;
            public byte alpha;

            /// <summary>
            /// Returns a string representation
            /// </summary>
            /// <returns></returns>
            public override string ToString()
            {
                return "(" + alpha.ToString() + ", " + red.ToString() + ", " + green.ToString() + ", " + blue.ToString() + ")";
            }
        }

        protected Bitmap m_WorkingBitmap = null;
        protected int width = 0;
        protected BitmapData m_BitmapData = null;
        protected Byte* m_pBase = null;

        /// <summary>
        /// New UnsafeBitmap() is not allowed
        /// </summary>
        internal UnsafeBitmap()
        {
        }

        public UnsafeBitmap(BitmapData imageData)
        {
            
            // allocate memory for the image
            IntPtr dstImageData = System.Runtime.InteropServices.Marshal.AllocHGlobal(imageData.Stride * imageData.Height);

            //CopyUnmanagedMemory(dstImageData, imageData.Scan0, imageData.Stride * imageData.Height);

        }
        /// <summary>
        /// See Bitmap(Size)
        /// </summary>
        /// <param name="_szSize"></param>
        public UnsafeBitmap(Size _szSize)
            : this(new Bitmap(_szSize.Width, _szSize.Height))
        {
        }

        /// <summary>
        /// See Bitmap(Width, Height)
        /// </summary>
        /// <param name="_nWidth"></param>
        /// <param name="_nHeight"></param>
        public UnsafeBitmap(int _nWidth, int _nHeight)
            : this(new Bitmap(_nWidth, _nHeight))
        {
        }

        /// <summary>
        /// Give caller possibility of new UnsafeBitmap(10,10, Graphics) like in new Bitmap(10,10, Graphics)
        /// </summary>
        /// <param name="_nWidth"></param>
        /// <param name="_nHeight"></param>
        /// <param name="_g"></param>
        public UnsafeBitmap(int _nWidth, int _nHeight, Graphics _g)
            : this(new Bitmap(_nWidth, _nHeight, _g))
        {
        }

        /// <summary>
        /// See Bitmap(Image)
        /// </summary>
        public UnsafeBitmap(Image _image)
            : this(new Bitmap(_image))
        {
        }

        /// <summary>
        /// See Bitmap(Stream)
        /// </summary>
        /// <param name="_stream"></param>
        public UnsafeBitmap(Stream _stream)
            : this(new Bitmap(_stream))
        {
        }

        /// <summary>
        /// See Bitmap(OriginalImage, szSize)
        /// </summary>
        /// <param name="_originalImage"></param>
        /// <param name="_szSize"></param>
        public UnsafeBitmap(Image _originalImage, Size _szSize)
            : this(new Bitmap(_originalImage, _szSize))
        {
        }

        /// <summary>
        /// See Image.FromHBitmap(IntPtr _hBitmap)
        /// </summary>
        /// <param name="_hBitmap"></param>
        public UnsafeBitmap(IntPtr _hBitmap)
            : this(Image.FromHbitmap(_hBitmap))
        {
        }

        /// <summary>
        /// See Image.FromHBitmap(IntPtr _hBitmap, IntPtr _hPalette)
        /// </summary>
        /// <param name="_hBitmap"></param>
        /// <param name="_hPalette"></param>
        public UnsafeBitmap(IntPtr _hBitmap, IntPtr _hPalette)
            : this(Image.FromHbitmap(_hBitmap, _hPalette))
        {
        }

        /// <summary>
        /// Use this to get an Image stream with or no embedded color management
        /// <seealso cref="Image.FromStream">Image.FromStream</seealso> for reference
        /// </summary>
        /// <param name="_stream"></param>
        /// <param name="_bUseEmbeddedColorManagement"></param>
        /// <param name="_bValidateData"></param>
        public UnsafeBitmap(Stream _stream, bool _bUseEmbeddedColorManagement, bool _bValidateData)
            : this(Image.FromStream(_stream, _bUseEmbeddedColorManagement, _bValidateData))
        {
        }

        /// <summary>
        /// new UnsafeBitmap("Name.jpg") like new Bitmap("Name.jpg")
        /// </summary>
        /// <param name="_sName"></param>
        public UnsafeBitmap(string _sName)
            : this(new Bitmap(_sName))
        {
        }

        /// <summary>
        /// like new Bitmap("Test", true) e.g.
        /// </summary>
        /// <param name="_sFileName"></param>
        /// <param name="_bUseIcm"></param>
        public UnsafeBitmap(string _sFileName, bool _bUseIcm)
            : this(new Bitmap(_sFileName, _bUseIcm))
        {
        }

        /// <summary>
        /// Like new Bitmap(Stream, true)
        /// </summary>
        /// <param name="_stream"></param>
        /// <param name="_bUseIcm"></param>
        public UnsafeBitmap(Stream _stream, bool _bUseIcm)
            : this(new Bitmap(_stream, _bUseIcm))
        {
        }

        /// <summary>
        /// creates a new UnsafeBitmap filled with pixel color _color
        /// </summary>
        /// <param name="_color"></param>
        /// <param name="_size"></param>
        public UnsafeBitmap(Color _color, Size _szSize)
            : this(new Bitmap(_szSize.Width, _szSize.Height))
        {
            this.Clear(_color);
        }

        /// <summary>
        /// Like new Bitmap(Bitmap)
        /// </summary>
        /// <param name="inputBitmap"></param>
        public UnsafeBitmap(Bitmap inputBitmap)
        {
            m_WorkingBitmap = inputBitmap;
            LockImage();
            m_nHeight = m_WorkingBitmap.Height;
            m_nWidth = m_WorkingBitmap.Width;
            m_nPixelCount = m_nWidth * m_nHeight;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_inputBitmap"></param>
        /// <param name="_pixelFormat"></param>
        public UnsafeBitmap(Bitmap _inputBitmap, PixelFormat _pixelFormat)
        {
            m_PixelFormat = _pixelFormat;
            m_WorkingBitmap = _inputBitmap;
            LockImage();
            m_nHeight = m_WorkingBitmap.Height;
            m_nWidth = m_WorkingBitmap.Width;
            m_nPixelCount = m_nWidth * m_nHeight;
        }

        /// <summary>
        /// Convert given byte array into bitmap
        /// </summary>
        /// <param name="_aByte">The _a byte.</param>
        public UnsafeBitmap(byte[] _aByte)
            : this(BitmapFunctions.ConvertFromMemoryStream(_aByte))
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UnsafeBitmap"/> class.
        /// </summary>
        /// <param name="_aByte">The _a byte.</param>
        /// <param name="_nWidth">Width of the _n.</param>
        /// <param name="_nHeight">Height of the _n.</param>
        public UnsafeBitmap(int[] _aByte, int _nWidth, int _nHeight)
            : this(new Bitmap(_nWidth, _nHeight))
        {
            int i = 0;
            Point point = Point.Empty;
            for (i = 0; i < _aByte.Length; i++)
            {
                point = GetCoordinatesFromIndex(i);
                this[point.X, point.Y] = Color.FromArgb(_aByte[i]);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_aByte"></param>
        /// <param name="_pixelFormat"></param>
        public UnsafeBitmap(byte[] _aByte, int _nWidth, int _nHeight, PixelFormat _pixelFormat)
            : this(ConvertToBitmap(_aByte, _pixelFormat, _nWidth, _nHeight, false))
        {
        }

        /// <summary>
        /// This is used to be able to clone the UnsafeBitmap
        /// </summary>
        /// <param name="_unsafeBitmap"></param>
        internal UnsafeBitmap(UnsafeBitmap _unsafeBitmap)
        {
            this.UnlockImage();
            this.m_WorkingBitmap = (Bitmap)_unsafeBitmap.m_WorkingBitmap.Clone();
            m_nHeight = m_WorkingBitmap.Height;
            m_nWidth = m_WorkingBitmap.Width;
            m_nPixelCount = m_nWidth * m_nHeight;
            this.LockImage();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UnsafeBitmap"/> class.
        /// </summary>
        /// <param name="_unsafeBitmap">The _unsafe bitmap.</param>
        /// <param name="size">The size.</param>
        internal UnsafeBitmap(UnsafeBitmap _unsafeBitmap, Size size)
        {
            this.UnlockImage();
            this.m_WorkingBitmap = new Bitmap((Bitmap)_unsafeBitmap.m_WorkingBitmap.Clone(), size);
            m_nHeight = m_WorkingBitmap.Height;
            m_nWidth = m_WorkingBitmap.Width;
            m_nPixelCount = m_nWidth * m_nHeight;
        }

        /// <summary>
        /// Froms the file.
        /// </summary>
        /// <param name="_sFileName">Name of the _s file.</param>
        /// <returns></returns>
        public static UnsafeBitmap FromFile(string _sFileName)
        {
            string sExtension = Path.GetExtension(_sFileName).ToLower();
            if (sExtension == ".pgm")
            {
                return PGM.Create(_sFileName);
            }
            else if (sExtension == ".ppm")
            {
                return PPM.Create(_sFileName);
            }
            else if (sExtension == ".pcx")
            {
                return new PCXLoader(_sFileName).Bitmap;
            }
            else if (sExtension == ".tif" || sExtension == ".tiff")
            {
                return Tiff.Create(_sFileName);
            }
            else if (sExtension == ".dxf")
            {
                return Dxf.Create(_sFileName);
            }
            else if (sExtension == ".svg")
            {
                return SVGReader.Create(_sFileName);
            }
            else if (sExtension == ".txt")
            {
                return Txt.Create(_sFileName);
            }
            else if (sExtension == ".rtf")
            {
                return Rtf.Create(_sFileName);
            }
            else if (sExtension == ".html"
                    || sExtension == ".htm")
            {
                return Html.Create(_sFileName);
            }
            else if (sExtension == ".psd")
            {
                return PSD.Create(_sFileName);
            }
            else
            {
                return new UnsafeBitmap(Image.FromFile(_sFileName));
            }
        }

        /// <summary>
        /// Froms the stream.
        /// </summary>
        /// <param name="_stream">The _stream.</param>
        /// <returns></returns>
        public static UnsafeBitmap FromStream(Stream _stream)
        {
            return new UnsafeBitmap(Image.FromStream(_stream));
        }

        /// <summary>
        /// Froms the stream.
        /// </summary>
        /// <param name="_stream">The _stream.</param>
        /// <param name="_bUseEmbeddedColorManagement">if set to <c>true</c> [_b use embedded color management].</param>
        /// <param name="_bValidateImageData">if set to <c>true</c> [_b validate image data].</param>
        /// <returns></returns>
        public static UnsafeBitmap FromStream(Stream _stream, bool _bUseEmbeddedColorManagement, bool _bValidateImageData)
        {
            return new UnsafeBitmap(Image.FromStream(_stream, _bUseEmbeddedColorManagement, _bValidateImageData));
        }

        /// <summary>
        /// Creates the scaled bitmap.
        /// </summary>
        /// <param name="_bitmap">The _bitmap.</param>
        /// <param name="_size">The _size.</param>
        /// <returns></returns>
        public static UnsafeBitmap CreateScaledClonedBitmap(UnsafeBitmap _bitmap, Size _size)
        {
            UnsafeBitmap bitmap = (UnsafeBitmap)_bitmap.Clone();
            bitmap = new UnsafeBitmap(bitmap, _size);
            return bitmap;
        }

        /// <summary>
        /// Saves this bitmap
        /// </summary>
        /// <param name="sSaveFileName"></param>
        public void Save(string _sSaveFileName)
        {
            UnlockImage();
            KnownImageFormats knownImageFormats = new KnownImageFormats();
            knownImageFormats.Save(_sSaveFileName, this);
            LockImage();
        }

        /// <summary>
        /// Return the set pixel Format
        /// You cannot set it at runtime
        /// </summary>
        public PixelFormat PixelFormat
        {
            get { return m_PixelFormat; }
        }

        //TODO: also implement for 3 bytes and other modes...
        /// <summary>
        /// Converts to bitmap.
        /// </summary>
        /// <param name="_aByte">The _a byte.</param>
        /// <param name="_pixelFormat">The _pixel format.</param>
        /// <param name="_nWidth">Width of the _n.</param>
        /// <param name="_nHeight">Height of the _n.</param>
        /// <param name="_bReverseOrder">if set to <c>true</c> [_b reverse order].</param>
        /// <returns></returns>
        protected static UnsafeBitmap ConvertToBitmap(byte[] _aByte, PixelFormat _pixelFormat, int _nWidth, int _nHeight, bool _bReverseOrder)
        {
            UnsafeBitmap bitmap = new Bitmap(_nWidth, _nHeight);
            int nBytesPerPixelCount = m_aBytesPerPixelCount[_pixelFormat];

            int nCount = 0;
            int y = 0;
            int x = 0;
            for (y = 0; y < _nHeight; y++)
            {
                for (x = 0; x < _nWidth; x++)
                {
                    bitmap.SetPixel(x, y,
                        _bReverseOrder ? Color.FromArgb(_aByte[0], _aByte[1], _aByte[2], _aByte[3]) : Color.FromArgb(_aByte[3], _aByte[2], _aByte[1], _aByte[0]));
                    nCount += nBytesPerPixelCount;
                }
            }
            bitmap.Dispose();
            return bitmap.InternalBitmap;
        }

        /// <summary>
        /// return ths Size of the pic
        /// </summary>
        public Size Size
        {
            get { return new Size(m_nWidth, m_nHeight); }
        }

        /// <summary>
        /// Return the complete pixel count of this pic
        /// Formula: Width * Height = PixelCount
        /// </summary>
        public int PixelCount
        {
            get { return m_nPixelCount; }
        }

        /// <summary>
        /// Return the BitmapData of the given bitmap
        /// </summary>
        public BitmapData BitmapData
        {
            get { return m_BitmapData; }
        }

        /// <summary>
        /// Performs an implicit conversion from <see cref="System.String"/> to <see cref="LowLevelGraphics.UnsafeBitmap"/>.
        /// </summary>
        /// <param name="_sString">The _s string.</param>
        /// <returns>The result of the conversion.</returns>
        public static implicit operator UnsafeBitmap(string _sString)
        {
            return UnsafeBitmap.FromFile(_sString);
        }

        /// <summary>
        /// Make it possible to do this: UnsafeBitmap b = new bitmap("Filename.jpg");
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public static implicit operator UnsafeBitmap(Bitmap _bitmap)
        {
            return new UnsafeBitmap(_bitmap);
        }

        /// <summary>
        /// Make it possible to do this: 
        /// Image image = Image.FromFile("Hello.jpg");
        /// UnsafeBitmap b = image;
        /// </summary>
        /// <param name="_image"></param>
        /// <returns></returns>
        public static implicit operator UnsafeBitmap(Image _image)
        {
            //if image is == null we should get an assert here!!!
            //Debug.Assert(_image == null);
            return new UnsafeBitmap((Bitmap)_image);
        }

        /// <summary>
        /// This enables modulo for bitmaps.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator %(UnsafeBitmap _b1, UnsafeBitmap _b2)
        {
            return new Modulo().Process(_b1, _b2);
        }

        /// <summary>
        /// This enables modulo for bitmaps.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator %(UnsafeBitmap _b1, int _nConstant)
        {
            return new Modulo().Process(_b1, _nConstant);
        }

        /// <summary>
        /// This enables modulo for bitmaps and constant.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator %(UnsafeBitmap _bitmap, byte _bConstant)
        {
            return new Modulo().Process(_bitmap, _bConstant);
        }

        /// <summary>
        /// Use this to ADD two pictures.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator +(UnsafeBitmap _b1, UnsafeBitmap _b2)
        {
            return new Add().Process(_b1, _b2);
        }

        /// <summary>
        /// Use this to ADD two pictures.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator +(UnsafeBitmap _bitmap, int _nConstant)
        {
            return new Add().Process(_bitmap, _nConstant);
        }

        /// <summary>
        /// Use this to ADD two pictures.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator +(UnsafeBitmap _bitmap, byte _bConstant)
        {
            return new Add().Process(_bitmap, _bConstant);
        }

        /// <summary>
        /// Use this to subtract two pictures.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator -(UnsafeBitmap _b1, UnsafeBitmap _b2)
        {
            return new Sub().Process(_b1, _b2);
        }

        /// <summary>
        /// Use this to subtract two pictures.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator -(UnsafeBitmap _bitmap, int _nConstant)
        {
            return new Sub().Process(_bitmap, _nConstant);
        }

        /// <summary>
        /// Use this to subtract two pictures.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator -(UnsafeBitmap _bitmap, byte _bConstant)
        {
            return new Sub().Process(_bitmap, _bConstant);
        }

        /// <summary>
        /// Use this to multiplicate two pictures.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator *(UnsafeBitmap _b1, UnsafeBitmap _b2)
        {
            return new Multiplizieren().Process(_b1, _b2);
        }

        /// <summary>
        /// Use this to multiplicate two pictures.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator *(UnsafeBitmap _b1, int _nConstant)
        {
            return new Multiplizieren().Process(_b1, _nConstant);
        }

        /// <summary>
        /// Use this to multiplicate two pictures.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator *(UnsafeBitmap _bitmap, byte _bConstant)
        {
            return new Multiplizieren().Process(_bitmap, _bConstant);
        }

        /// <summary>
        /// Use this two divide two pictures.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator /(UnsafeBitmap _b1, UnsafeBitmap _b2)
        {
            return new Divide().Process(_b1, _b2);
        }

        /// <summary>
        /// Use this two divide two pictures.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator /(UnsafeBitmap _bitmap, int _nConstant)
        {
            return new Divide().Process(_bitmap, _nConstant);
        }

        /// <summary>
        /// Use this two divide two pictures.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator /(UnsafeBitmap _bitmap, byte _bConstant)
        {
            return new Divide().Process(_bitmap, _bConstant);
        }

        /// <summary>
        /// Use this for a logical not (!) of a picture. 
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator !(UnsafeBitmap _bitmap)
        {
            new Invert().Execute(_bitmap);
            return _bitmap;
        }

        /// <summary>
        /// Use this to logical AND (bitmap1 and bitmap2) two pictures.
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator &(UnsafeBitmap _b1, UnsafeBitmap _b2)
        {
            return new And().Process(_b1, _b2);
        }

        /// <summary>
        /// Use this to logical AND (bitmap and int)
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator &(UnsafeBitmap _bitmap, int _nConstant)
        {
            return new And().Process(_bitmap, _nConstant);
        }

        /// <summary>
        /// Use this to logical AND (bitmap and int)
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator &(UnsafeBitmap _bitmap, byte _bConstant)
        {
            return new And().Process(_bitmap, _bConstant);
        }

        /// <summary>
        /// Use this for a logical xor for two pictures (^)
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator ^(UnsafeBitmap _b1, UnsafeBitmap _b2)
        {
            return new XOR().Process(_b1, _b2);
        }

        /// <summary>
        /// Use this for a logical xor for two pictures (^)
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator ^(UnsafeBitmap _bitmap, int _nConstant)
        {
            return new XOR().Process(_bitmap, _nConstant);
        }

        /// <summary>
        /// Use this for a logical xor for two pictures (^)
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator ^(UnsafeBitmap _bitmap, byte _bConstant)
        {
            return new XOR().Process(_bitmap, _bConstant);
        }

        /// <summary>
        /// Use this for a logical or of two pictures (|)
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator |(UnsafeBitmap _b1, UnsafeBitmap _b2)
        {
            return new OR().Process(_b1, _b2);
        }

        /// <summary>
        /// Use this for a logical or of two pictures (|)
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator |(UnsafeBitmap _bitmap, int _nConstant)
        {
            return new OR().Process(_bitmap, _nConstant);
        }

        /// <summary>
        /// Use this for a logical or of two pictures (|)
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_b2"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator |(UnsafeBitmap _bitmap, byte _bConstant)
        {
            return new OR().Process(_bitmap, _bConstant);
        }

        /// <summary>
        /// This will do a RIGHT shift
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_nBits"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator >>(UnsafeBitmap _b1, int _nBits)
        {
            return new ImageBitShift(_nBits).ExecuteCloned(_b1);
        }

        /// <summary>
        /// This will do a LEFT bitshift
        /// </summary>
        /// <param name="_b1"></param>
        /// <param name="_nBits"></param>
        /// <returns></returns>
        public static UnsafeBitmap operator <<(UnsafeBitmap _b1, int _nBits)
        {
            return new ImageBitShift(_nBits).ExecuteCloned(_b1);
        }


        //TODO: UnsafeBitmap, Palette: How to get only the palette, without having to walk through the whole pic
        /// <summary>
        /// This gets a palette of an image.
        /// 
        /// This uses a lazy initialization, i.e. if we never called this property
        /// for this pic before, the whole bitmap is walked through to get the palette information
        /// 
        /// </summary>
        public HashSet<Color> Palette
        {
            get
            {
                //Lazy initialization
                //calculate Palette if it is empty or contains nothing
                if (m_aPalette == null || m_aPalette.Count == 0)
                {
                    HashSet<Color> color = new HashSet<Color>();
                    int nHeight = this.Height;
                    int nWidth = this.Width;
                    int y = 0;
                    int x = 0;
                    for (y = 0; y < nHeight; y++)
                    {
                        for (x = 0; x < nWidth; x++)
                        {
                            color.Add(this.GetPixelDirect(x, y));
                        }
                    }
                    m_aPalette = color;
                }
                return m_aPalette;
            }
        }

        /// <summary>
        /// Generate foreground edge from background edge
        /// </summary>
        public void GenerateForegroundEdgeFromBackgroundEdge()
        {
            m_ForegroundEdgePixels.Clear();
            Point p, p2;
            IEnumerator it = m_BackgroundEdgePixels.GetEnumerator();
            int nWidth = this.Width;
            int nHeight = this.Height;

            int j = 0;
            int i = 0;

            while (it.MoveNext())
            {
                p = (Point)it.Current;
                for (j = -1; j < 2; ++j)
                {
                    for (i = -1; i < 2; ++i)
                    {
                        if ((p.X + i >= 0) && (p.X + i < nWidth) && (p.Y + j >= 0) && (p.Y + j < nHeight))
                        {
                            p2 = new Point(p.X + i, p.Y + j);
                            if (this.GetPixel(p2.X, p2.Y) == Definitions.White)
                            {
                                m_ForegroundEdgePixels.Add(p2);
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Generate Pixels for edge pixels
        /// </summary>
        /// <param name="pix"></param>
        public void GeneratePixels(HashSet pix)
        {
            int nHeight = this.Height;
            int nWidth = this.Width;
            //Reset all pixels to background
            int j = 0;
            int i = 0;
            for (j = 0; j < nHeight; ++j)
            {
                for (i = 0; i < nWidth; ++i)
                {
                    this.SetPixel(i, j, Definitions.Black);
                }
            }
            ConvertToPixels(pix);
        }

        /// <summary>
        /// Adds the pixels from a hash set to the 2D array of pixels.
        /// </summary>
        /// <param name="pix">The hash set of foreground pixels to be added.</param>
        public void ConvertToPixels(HashSet pix)
        {
            //int i = 0;
            Point p = new Point();
            IEnumerator it = pix.GetEnumerator();
            while (it.MoveNext())
            {
                p = (Point)it.Current;
                this.SetPixel(p.X, p.Y, Definitions.White);
            }
        }

        /// <summary>
        /// Initialize edge pixels
        /// </summary>
        public void InitializeEdgePixels()
        {
            this.GenerateForegroundEdge();
            this.GenerateBackgroundEdgeFromForegroundEdge();
        }

        /// <summary>
        /// Generate Background edge pixels
        /// </summary>
        public void GenerateBackgroundEdgeFromForegroundEdge()
        {
            m_BackgroundEdgePixels.Clear();
            Point p, p2;
            IEnumerator it = m_ForegroundEdgePixels.GetEnumerator();
            int nHeight = this.Height;
            int nWidth = this.Width;

            int j = 0;
            int i = 0;

            while (it.MoveNext())
            {
                p = (Point)it.Current;
                for (j = -1; j < 2; ++j)
                {
                    for (i = -1; i < 2; ++i)
                    {
                        if ((p.X + i >= 0) && (p.X + i < nWidth) && (p.Y + j >= 0) && (p.Y + j < nHeight))
                        {
                            p2 = new Point(p.X + i, p.Y + j);
                            if (this.GetPixel(p2.X, p2.Y) == Definitions.Black)
                            {
                                m_BackgroundEdgePixels.Add(p2);
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Generate foregroundedge pixels
        /// </summary>
        /// <returns></returns>
        public IEnumerator GenerateForegroundEdge()
        {
            m_ForegroundEdgePixels.Clear();
            Point p;

            int nHeight = this.Height;
            int nWidth = this.Width;

            int n = 0;
            int m = 0;
            int j = 0;
            int i = 0;

            for (n = 0; n < nHeight; ++n)
            {
                for (m = 0; m < nWidth; ++m)
                {
                    if (this.GetPixel(m, n) == Definitions.White)
                    {
                        p = new Point(m, n);
                        for (j = -1; j < 2; ++j)
                        {
                            for (i = -1; i < 2; ++i)
                            {
                                if ((p.X + i >= 0) && (p.X + i < nWidth) && (p.Y + j >= 0) && (p.Y + j < nHeight))
                                {
                                    if ((this.GetPixel(p.X + i, p.Y + j) == Definitions.Black) &&
                                       (!m_ForegroundEdgePixels.Contains(p)))
                                    {
                                        m_ForegroundEdgePixels.Add(p);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return m_ForegroundEdgePixels.GetEnumerator();
        }

        /// <summary>
        /// Adds a white pixel
        /// </summary>
        /// <param name="p"></param>
        public void AddPixel(Point p)
        {
            this.SetPixel(p.X, p.Y, Definitions.White);
        }

        /// <summary>
        /// Removes a black Pixel
        /// </summary>
        /// <param name="p"></param>
        public void RemovePixel(Point p)
        {
            this.SetPixel(p.X, p.Y, Definitions.Black);
        }

        /// <summary>
        /// Get the Int-Pointer of this UnsafeBitmap
        /// </summary>
        public IntPtr IntPtr
        {
            get { return new IntPtr(m_pBase); }
        }

        /// <summary>
        /// Returns the normal Bitmap
        /// </summary>
        public Bitmap InternalBitmap
        {
            get { return m_WorkingBitmap; }
        }

        /// <summary>
        /// Tries to lock the image
        /// </summary>
        /// <returns>TRUE => Success, FALSE => bad luck</returns>
        public virtual bool LockImage()
        {
            if (m_WorkingBitmap == null) return false;
            Rectangle bounds = new Rectangle(Point.Empty, m_WorkingBitmap.Size);

            width = (int)(bounds.Width * sizeof(PixelData));
            if (width % 4 != 0) width = 4 * (width / 4 + 1);

            //Lock Image
            m_BitmapData = m_WorkingBitmap.LockBits(bounds, ImageLockMode.ReadWrite, m_PixelFormat);
            m_pBase = (Byte*)m_BitmapData.Scan0.ToPointer();
            return true;
        }

        /// <summary>
        /// return pixel at UnsafeBitmap[x,y]
        /// </summary>
        /// <param name="_nX"></param>
        /// <param name="_nY"></param>
        /// <returns></returns>
        public Color this[int _nX, int _nY]
        {
            get { return GetPixel(_nX, _nY); }
            set { SetPixel(_nX, _nY, value); }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_nX"></param>
        /// <param name="_nY"></param>
        /// <returns></returns>
        public uint this[uint _nX, uint _nY]
        {
            get { return GetPixelAsUInt(_nX, _nY); }
            set { SetPixel((int)_nX, (int)_nY, Color.FromArgb((int)value)); }
        }


        //rgb channel 1
        //FF0000
        //00FF00
        //0000FF

        /// <summary>
        /// Gets or sets the <see cref="System.Byte"/> with the specified _n X.
        /// </summary>
        /// <value></value>
        public byte this[int _nX, int _nY, int _nChannel]
        {
            get
            {
                Color color = GetPixelDirect(_nX, _nY);
                if (_nChannel == 0)
                {
                    return color.R;
                }
                else if (_nChannel == 1)
                {
                    return color.G;
                }
                else if (_nChannel == 2)
                {
                    return color.B;
                }
                else
                {
                    throw new Exception("Channel does not exist");
                }
            }

            set
            {
                Color color = GetPixelDirect(_nX, _nY);
                byte r = 0;
                byte g = 0;
                byte b = 0;
                byte bValue = value;

                if (_nChannel == 0)
                {
                    r = value;
                }
                else if (_nChannel == 1)
                {
                    g = value;
                }
                else if (_nChannel == 2)
                {
                    b = value;
                }
                else
                {
                    throw new Exception("Channel does not exist");
                }
                SetPixelDirect(_nX, _nY, Color.FromArgb(r, g, b));
            }
        }

        /// <summary>
        /// Gets or sets the <see cref="System.Byte"/> with the specified _n X.
        /// </summary>
        /// <value></value>
        public byte this[int _nX, int _nY, RGBChannel _nChannel]
        {
            get
            {
                byte[] argb = new byte[4];
                GetPixelDirect(_nX, _nY, out argb[0], out argb[1], out argb[2], out argb[3]);
                return argb[(int)_nChannel];
            }

            set
            {
                byte[] argb = new byte[4];
                GetPixelDirect(_nX, _nY, out argb[0], out argb[1], out argb[2], out argb[3]);
                argb[(int)_nChannel] = value;
                SetPixelDirect(_nX, _nY, Color.FromArgb(argb[0], argb[1], argb[2], argb[3]));
            }
        }

        /// <summary>
        /// Return the n-th pixel of the UnsafeBitmap
        /// </summary>
        /// <param name="_nIndex"></param>
        /// <returns></returns>
        public int this[int _nIndex]
        {
            get
            {
                PixelData* pixelData = (PixelData*)(m_pBase + _nIndex * sizeof(PixelData));
                return Color.FromArgb(pixelData->alpha, pixelData->red, pixelData->green, pixelData->blue).ToArgb();
            }
        }

        /// <summary>
        /// Return UnsafeBitmap[x,y] as gray color
        /// </summary>
        /// <param name="_nX"></param>
        /// <param name="_nY"></param>
        /// <param name="_bGray"></param>
        /// <returns></returns>
        public Color this[int _nX, int _nY, bool _bGray]
        {
            get { return ColorFunctions.GrayColor(GetPixel(_nX, _nY)); }
        }

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="_nX"></param>
        ///// <param name="_nY"></param>
        ///// <param name="_MODE"></param>
        ///// <returns></returns>
        public int this[int _nX, int _nY, PIXEL_MODE _MODE]
        {
            get
            {
                int nValue = -1;

                Color color = GetPixel(_nX, _nY);

                switch (_MODE)
                {
                    case PIXEL_MODE.COLOR_UINT:
                        nValue = (int)this[(uint)_nX, (uint)_nY];
                        break;

                    case PIXEL_MODE.GRAY_VALUE:
                        nValue = ColorFunctions.Gray(color);
                        break;

                    case PIXEL_MODE.COLOR_ARGB_VALUE:
                        nValue = color.ToArgb();
                        break;

                    case PIXEL_MODE.COLOR_INTRGB_VALUE:
                        nValue = ColorFunctions.ToIntRGB(color);
                        break;
                }
                return nValue;
            }

            set 
            {
                switch (_MODE)
                {
                    case PIXEL_MODE.COLOR_UINT:
                        this[(uint)_nX, (uint)_nY] = (uint)value;
                        break;

                    case PIXEL_MODE.GRAY_VALUE:
                        SetGrayPixel(_nX, _nY, value);
                        break;

                    case PIXEL_MODE.COLOR_INTRGB_VALUE:
                        SetPixel(_nX, _nY, Color.FromArgb(value));
                        break;

                    case PIXEL_MODE.COLOR_ARGB_VALUE:
                        SetPixel(_nX, _nY, Color.FromArgb(255, Color.FromArgb(value)));
                        break;
                }
            }
        }

        /// <summary>
        /// Set a Gray pixel, i.e. all channels will get the same value
        /// </summary>
        /// <param name="_nX"></param>
        /// <param name="_nY"></param>
        /// <param name="_nGrayValue"></param>
        public void SetGrayPixel(int _nX, int _nY, int _nGrayValue)
        {
            SetPixel(_nX, _nY, Color.FromArgb(_nGrayValue, _nGrayValue, _nGrayValue));
        }

        /// <summary>
        /// Gets the gray pixel
        /// </summary>
        /// <param name="_nX"></param>
        /// <param name="_nY"></param>
        /// <returns></returns>
        public Color GetGrayPixel(int _nX, int _nY)
        {
            return ColorFunctions.GrayColor(GetPixel(_nX, _nY));
        }

        /// <summary>
        /// Gets the Gray value of the pixel
        /// </summary>
        /// <param name="_nX"></param>
        /// <param name="_nY"></param>
        /// <returns></returns>
        public int GetGrayPixelValue(int _nX, int _nY)
        {
            return ColorFunctions.Gray(GetPixel(_nX, _nY));
        }

        /// <summary>
        /// Get pixel corresponding to Bitmap.GetPixel()
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public Color GetPixel(int x, int y)
        {
            m_PixelData = (PixelData*)(m_pBase + y * width + x * sizeof(PixelData));
            return Color.FromArgb(m_PixelData->alpha, m_PixelData->red, m_PixelData->green, m_PixelData->blue);
        }

        /// <summary>
        /// Gets the pixel R.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <returns></returns>
        public int GetPixelR(int x, int y)
        {
            m_PixelData = (PixelData*)(m_pBase + y * width + x * sizeof(PixelData));
            return m_PixelData->red;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public uint GetPixelAsUInt(uint x, uint y)
        {
            m_PixelData = (PixelData*)(m_pBase + y * width + x * sizeof(PixelData));
            return (uint)Color.FromArgb(m_PixelData->alpha, m_PixelData->red, m_PixelData->green, m_PixelData->blue).ToArgb();
        }

        /// <summary>
        /// Gets the pixel G.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <returns></returns>
        public int GetPixelG(int x, int y)
        {
            m_PixelData = (PixelData*)(m_pBase + y * width + x * sizeof(PixelData));
            return m_PixelData->green;
        }

        /// <summary>
        /// Gets the pixel B.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <returns></returns>
        public int GetPixelB(int x, int y)
        {
            m_PixelData = (PixelData*)(m_pBase + y * width + x * sizeof(PixelData));
            return m_PixelData->blue;
        }

        /// <summary>
        /// Gets the pixel.
        /// </summary>
        /// <param name="pt">The pt.</param>
        /// <returns></returns>
        public Color GetPixel(Point pt)
        {
            return GetPixel(pt.X, pt.Y);
        }

        /// <summary>
        /// Gets the pixel long.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <returns></returns>
        public long GetPixelLong(int x, int y)
        {
            m_PixelData = (PixelData*)(m_pBase + y * width + x * sizeof(PixelData));
            return (long)m_PixelData;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public long GetPixelLongArgb(int x, int y)
        {
            m_PixelData = (PixelData*)(m_pBase + y * width + x * sizeof(PixelData));
            //Extracted from Color.FromArgb()
            return (long)(((ulong)((((m_PixelData->red << 0x10) | (m_PixelData->green << 8)) | m_PixelData->blue) | (m_PixelData->alpha << 0x18))) & 0xffffffffL);
        }

        /// <summary>
        /// Get next pixel by increasing pointer address
        /// </summary>
        /// <returns></returns>
        public Color GetNextPixel()
        {
            PixelData* pixelData = (PixelData*)(m_pBase + m_PixelDataGetNextPixelIndex * sizeof(PixelData));
            m_PixelDataGetNextPixelIndex++;
            return Color.FromArgb(pixelData->alpha, pixelData->red, pixelData->green, pixelData->blue);
        }

        /// <summary>
        /// Gets the next pixel long
        /// </summary>
        /// <returns></returns>
        public long GetNextPixelLongArgb()
        {
            PixelData* pixelData = (PixelData*)(m_pBase + m_PixelDataGetNextPixelIndex * sizeof(PixelData));
            m_PixelDataGetNextPixelIndex++;
            return (long)(((ulong)((((m_PixelData->red << 0x10) | (m_PixelData->green << 8)) | m_PixelData->blue) | (m_PixelData->alpha << 0x18))) & 0xffffffffL);
        }

        /// <summary>
        /// Gets the next pixel long.
        /// </summary>
        /// <returns></returns>
        public long GetNextPixelLong()
        {
            PixelData* pixelData = (PixelData*)(m_pBase + m_PixelDataGetNextPixelIndex * sizeof(PixelData));
            m_PixelDataGetNextPixelIndex++;
            return (long)m_PixelData;
        }

        /// <summary>
        /// Gets the next pixel reset.
        /// </summary>
        public void GetNextPixelReset()
        {
            m_PixelDataGetNextPixelIndex = 0;
        }

        /// <summary>
        /// Sets the current pixel.
        /// </summary>
        /// <param name="_color">The _color.</param>
        public void SetCurrentPixel(Color _color)
        {
            PixelData* pixelData = (PixelData*)(m_pBase + m_PixelDataGetNextPixelIndex * sizeof(PixelData));
            pixelData->alpha = _color.A;
            pixelData->red = _color.R;
            pixelData->green = _color.G;
            pixelData->blue = _color.B;
        }

        /// <summary>
        /// Sets the current pixel.
        /// </summary>
        /// <param name="a">A.</param>
        /// <param name="r">The r.</param>
        /// <param name="g">The g.</param>
        /// <param name="b">The b.</param>
        public void SetCurrentPixel(byte a, byte r, byte g, byte b)
        {
            PixelData* pixelData = (PixelData*)(m_pBase + m_PixelDataGetNextPixelIndex * sizeof(PixelData));
            pixelData->alpha = a;
            pixelData->red = r;
            pixelData->green = g;
            pixelData->blue = b;
        }

        /// <summary>
        /// Sets the current pixel.
        /// </summary>
        /// <param name="r">The r.</param>
        /// <param name="g">The g.</param>
        /// <param name="b">The b.</param>
        public void SetCurrentPixel(byte r, byte g, byte b)
        {
            PixelData* pixelData = (PixelData*)(m_pBase + m_PixelDataGetNextPixelIndex * sizeof(PixelData));
            pixelData->alpha = 255;
            pixelData->red = r;
            pixelData->green = g;
            pixelData->blue = b;
        }

        /// <summary>
        /// GetPixels
        /// </summary>
        /// <returns></returns>
        public object[] GetPixels(bool _bTest)
        {
            int nWidth = this.Width;
            int nHeight = this.Height;
            object[] aColor = new object[nHeight * nWidth];
            int nIndex = 0;
            int y = 0;
            int x = 0;
            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    aColor[nIndex] = this.GetPixelDirect(x, y);
                    nIndex++;
                }
            }
            //TODO:
            //Array.ForEach<Color>(aColor, delegate(Color x) { Console.WriteLine(x); });
            return aColor;
        }

        /// <summary>
        /// Gets all the pixels
        /// </summary>
        /// <returns></returns>
        public object[] GetPixels()
        {
            return GetPixels(new SingleIntValuePixelDelegate(x => x));
        }

        /// <summary>
        /// Get pixels by specifying a delegate
        /// </summary>
        /// <param name="_delegate"></param>
        /// <returns></returns>
        public object[] GetPixels(SingleIntValuePixelDelegate _delegate)
        {
            int nHeight = this.Height;
            int nWidth = this.Width;
            object[] aColor = new object[nHeight * nWidth];
            int nIndex = 0;
            
            int y = 0;
            int x = 0;

            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    aColor[nIndex] = _delegate(this.GetPixelDirect(x, y).ToArgb());
                    nIndex++;
                }
            }
            return aColor;
        }

        /// <summary>
        /// Get pixels in given PROCESSING_MODE
        /// </summary>
        /// <param name="_processingMode"></param>
        /// <returns></returns>
        public object[] GetPixels(PROCESSING_MODE _processingMode)
        {
            ColorCalculation colorCalculation = Definitions.ColorCalculationDictionaryProcessingMode[_processingMode];
            int nHeight = this.Height;
            int nWidth = this.Width;
            object[] aColor = new object[nHeight * nWidth];
            int nIndex = 0;

            int y = 0;
            int x = 0;

            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    aColor[nIndex] = colorCalculation(this.GetPixel(x, y));
                    nIndex++;
                }
            }
            return aColor;
        }

        //TODO: UnsafeBitmap, GetPixelArray: check if this is obsolete
        /// <summary>
        /// Gets the pixel array.
        /// </summary>
        /// <returns></returns>
        public Dictionary<Point, Color> GetPixelArray()
        {
            return null;
        }

        //TODO: UnsafeBitmap, GetPixelArrayCopy: check if this is obsolete
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Dictionary<Point, Color> GetPixelArrayCopy()
        {
            Dictionary<Point, Color> aColor = new Dictionary<Point, Color>();
            int y = 0;
            int x = 0;
            int nWidth = this.Width;
            int nHeight = this.Height;

            for (y = 0; y < nWidth; y++)
            {
                for (x = 0; x < nHeight; x++)
                {
                    aColor.Add(new Point(x, y), this.GetPixel(x, y));
                }
            }
            return aColor;
        }

        public PixelDataCoordinates[] GetAsPixelDataCoordinateArray()
        {
            int x = 0;
            int y = 0;
            int nWidth = this.m_WorkingBitmap.Width;
            int nHeight = this.m_WorkingBitmap.Height;
            List<PixelDataCoordinates> aPixelDataCoordinates = new List<PixelDataCoordinates>();
            
            for (y = 0; y < nHeight; y++)
            {
                for (x= 0; x < nWidth; x++)
                {
                    aPixelDataCoordinates.Add(new PixelDataCoordinates());
                }
            }
            return aPixelDataCoordinates.ToArray();
        }

        /// <summary>
        /// Gets as pixel array int.
        /// </summary>
        /// <returns></returns>
        public int[,] GetAsPixelArrayInt()
        {
            int nWidth = this.Width;
            int nHeight = this.Height;
            int[,] aInt = new int[nWidth, nHeight];

            int y = 0;
            int x = 0;

            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    aInt[x, y] = this.GetPixelDirectInt(x, y);
                }
            }
            return aInt;
        }

        /// <summary>
        /// Gets as pixel array long.
        /// </summary>
        /// <returns></returns>
        public long[,] GetAsPixelArrayLong()
        {
            int nWidth = this.Width;
            int nHeight = this.Height;
            long[,] aLong = new long[nWidth, nHeight];

            int y = 0;
            int x = 0;

            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    aLong[x, y] = this.GetPixelLong(x, y);
                }
            }
            return aLong;
        }

        /// <summary>
        /// Gets the color of as pixel array.
        /// </summary>
        /// <returns></returns>
        public Color[,] GetAsPixelArrayColor()
        {
            int nWidth = this.Width;
            int nHeight = this.Height;
            Color[,] aColor = new Color[nWidth, nHeight];

            int y = 0;
            int x = 0;

            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    aColor[x, y] = this.GetPixel(x, y);
                }
            }
            return aColor;
        }

        /*public List<Color> GetPixelArray()
        {
            List<Color> aColor = new List<Color>();
            for (int i = 0; i < this.width * this.Height; i++)
            {
                aColor.Add(GetNextPixel());
            }
            return aColor;
        }*/

        private const int nPixelSize = 4;
        private byte* row = null;

        /// <summary>
        /// this uses a very fast set
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="color"></param>
        public void SetPixelDirect(int x, int y, Color color)
        {
            row = (byte*)m_BitmapData.Scan0 + (y * m_BitmapData.Stride);
            int nOffset0 = x * nPixelSize;
            row[nOffset0 + 3] = color.A;
            row[nOffset0 + 2] = color.R;
            row[nOffset0 + 1] = color.G;
            row[nOffset0 + 0] = color.B;
        }

        /// <summary>
        /// Sets the pixel direct.
        /// </summary>
        /// <param name="_pt">The _PT.</param>
        /// <param name="_color">The _color.</param>
        public void SetPixelDirect(Point _pt, Color _color)
        {
            SetPixelDirect(_pt.X, _pt.Y, _color);
        }

        /// <summary>
        /// This also uses the fastest set, overload
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="a"></param>
        /// <param name="r"></param>
        /// <param name="g"></param>
        /// <param name="b"></param>
        public void SetPixelDirect(int x, int y, byte a, byte r, byte g, byte b)
        {
            row = (byte*)m_BitmapData.Scan0 + (y * m_BitmapData.Stride);
            int nOffset0 = x * nPixelSize;
            row[nOffset0 + 3] = a;
            row[nOffset0 + 2] = r;
            row[nOffset0 + 1] = g;
            row[nOffset0 + 0] = b;
        }

        /// <summary>
        /// This uses the fastest set
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="r"></param>
        /// <param name="g"></param>
        /// <param name="b"></param>
        public void SetPixelDirect(int x, int y, byte r, byte g, byte b)
        {
            row = (byte*)m_BitmapData.Scan0 + (y * m_BitmapData.Stride);
            int nOffset0 = x * nPixelSize;
            row[nOffset0 + 3] = 255;
            row[nOffset0 + 2] = r;
            row[nOffset0 + 1] = g;
            row[nOffset0 + 0] = b;
        }

        /// <summary>
        /// Gets the pixel direct.
        /// </summary>
        /// <param name="_pt">The _PT.</param>
        /// <returns></returns>
        public Color GetPixelDirect(Point _pt)
        {
            return GetPixelDirect(_pt.X, _pt.Y);
        }

        /// <summary>
        /// This uses a very fast get
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public Color GetPixelDirect(int x, int y)
        {
            row = (byte*)m_BitmapData.Scan0 + (y * m_BitmapData.Stride);
            int nOffset0 = x * nPixelSize;
            return Color.FromArgb(row[nOffset0 + 3], row[nOffset0 + 2], row[nOffset0 + 1], row[nOffset0 + 0]);
        }

        /// <summary>
        /// This is also a very fast get
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public int GetPixelDirectInt(int x, int y)
        {
            row = (byte*)m_BitmapData.Scan0 + (y * m_BitmapData.Stride);
            int nOffset0 = x * nPixelSize;
            int a = row[nOffset0 + 3];
            int r = row[nOffset0 + 2];
            int g = row[nOffset0 + 1];
            int b = row[nOffset0 + 0];
            return (r << 16) + (g << 8) + b;
        }

        /// <summary>
        /// This uses a very fast get
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public void GetPixelDirect(int x, int y, out byte a, out byte r, out byte g, out byte b)
        {
            row = (byte*)m_BitmapData.Scan0 + (y * m_BitmapData.Stride);
            int nOffset0 = x * nPixelSize;
            a = row[nOffset0 + 3];
            r = row[nOffset0 + 2];
            g = row[nOffset0 + 1];
            b = row[nOffset0 + 0];
        }

        /// <summary>
        /// Returns the Offset Pointer increasing.
        /// U need this for still using this.BitmapData and then increasing pointer
        /// </summary>
        public int OffsetPointerIncrease
        {
            get
            {
                int nOffset = this.m_BitmapData.Stride - this.m_BitmapData.Width * BytesPerPixelCount;
                return nOffset;
            }
        }

        /// <summary>
        /// Returns the bytes per pixel count
        /// </summary>
        public int BytesPerPixelCount
        {
            get { return m_aBytesPerPixelCount[m_PixelFormat]; }
        }

        /// <summary>
        /// Sets the pixel.
        /// </summary>
        /// <param name="_ptPoint">The _PT point.</param>
        /// <returns></returns>
        public bool SetPixel(Point _ptPoint, Color _color)
        {
            this.SetPixel(_ptPoint.X, _ptPoint.Y, _color);
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="color"></param>
        /// <returns></returns>
        public bool SetPixel(int x, int y, Color color)
        {
            PixelData* data = (PixelData*)(m_pBase + y * width + x * sizeof(PixelData));
            data->alpha = color.A;
            data->red = color.R;
            data->green = color.G;
            data->blue = color.B;
            return true;
        }

        /// <summary>
        /// Unlocks the image
        /// </summary>
        /// <returns></returns>
        public bool UnlockImage()
        {
            bool bUnlockResult = false;
            if (m_BitmapData != null)
            {
                m_WorkingBitmap.UnlockBits(m_BitmapData);
                bUnlockResult = true;
            }
            else
            {
                bUnlockResult = false;
                Debug.WriteLine("Can't unlock when bitmapData is already null!");
            }
            m_BitmapData = null;
            m_pBase = null;
            return bUnlockResult;
        }

        /// <summary>
        /// Gets the index of the coordinates from.
        /// </summary>
        /// <param name="_nIndex">Index of the _n.</param>
        /// <returns></returns>
        public Point GetCoordinatesFromIndex(int _nIndex)
        {
            int _nX = _nIndex % m_WorkingBitmap.Width; //this.Width;
            int _nY = _nIndex / m_WorkingBitmap.Width; //this.Width;
            return new Point(_nX, _nY);
        }

        /// <summary>
        /// Gets the index from coordinates.
        /// </summary>
        /// <param name="_nX">The _n X.</param>
        /// <param name="_nY">The _n Y.</param>
        /// <returns></returns>
        public int GetIndexFromCoordinates(int _nX, int _nY)
        {
            return _nX + m_WorkingBitmap.Width * _nY; //this.Width
        }


        #region IBitmap Members

        /// <summary>
        /// Returns the height of the pic
        /// </summary>
        public int Height
        {
            get { return m_WorkingBitmap.Height; }
        }

        /// <summary>
        /// Returns the width of the pic
        /// </summary>
        public int Width
        {
            get { return m_WorkingBitmap.Width; }
        }

        /// <summary>
        /// Clears the content of the pic
        /// </summary>
        public void Clear()
        {
            Clear(Color.Black);
        }

        /// <summary>
        /// Clears the pic.
        /// </summary>
        /// <param name="_color"></param>
        public void Clear(Color _color)
        {
            //TODO: Can this be done faster by a marshal.copy statement or similar things?!
            int y = 0;
            int x = 0;

            int nHeight = this.Height;
            int nWidth = this.Width;

            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    this.SetPixel(x, y, _color);
                }
            }
        }

        /// <summary>
        /// Dispose Unlocks the internal image. 
        /// </summary>
        public void Dispose()
        {
            UnlockImage();
        }

        #endregion

        #region ICloneable Members

        /// <summary>
        /// Clones this object. To be able to clone it, 
        /// the bitmap will be unlocked and relocked again
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            return new UnsafeBitmap(this);
        }

        #endregion
    }
}
